Skip to content

security(data-plane): canonical percent-decode, raw header limits, admin exposure warning#97

Merged
ndreno merged 1 commit into
mainfrom
security/data-plane-misc
Jul 2, 2026
Merged

security(data-plane): canonical percent-decode, raw header limits, admin exposure warning#97
ndreno merged 1 commit into
mainfrom
security/data-plane-misc

Conversation

@ndreno

@ndreno ndreno commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Area 3 — data-plane misc (#9)

Final area of the sequential security pass.

DP-4 — percent-decode / path confusion

The query decoder built each %XX byte via byte as char, which corrupts multi-byte UTF-8 (e.g. %C3%A9 → two garbage chars instead of é), skewing validation. Replaced with a single canonical, UTF-8-correct percent_decode (byte buffer + from_utf8_lossy), and applied it to captured path-parameter values too — so routing, validation, and dispatch all see the same decoded value. Path segments are still matched raw, so %2F remains a literal slash within its segment rather than acting as a separator (no encoded-slash confusion introduced).

DP-5 — header-count dedup

Header limits were enforced on a HashMap that collapses duplicate names, so repeated headers undercounted the limit and only the last value for a name was size-checked. Limits are now enforced on the raw HeaderMap (len() counts every line; each value size-checked) before the map is built for downstream use.

DP-8 — admin exposure

/health, /metrics, /provenance are unauthenticated by design (scraping), but /provenance and /metrics leak build/operational metadata. The admin server now logs a startup warning when bound to a non-loopback address, and the behavior is documented.

Deferred

AR rebinding residual (resolve-then-connect TOCTOU: reqwest re-resolves at connect, so a rebinding attacker could still reach an internal IP): closing it properly means moving the SSRF check into a custom DNS resolver for the WASM HTTP client — a cross-cutting refactor. Kept tracked in #9.

Verification

  • New unit tests: percent_decode UTF-8 correctness + malformed-escape passthrough; raw header count/size limits.
  • CI gates green locally (fmt, clippy, workspace unit tests).
  • Ran the affected integration suites locally: routing and validation (updated one stale assertion to the RFC-correct 413 for oversized bodies, from PR security(data-plane): ingress DoS hardening + chunked body-size cap #94) and the full security suite (21 passed / 4 ignored).

Resolves the data-plane items tracked in #9 (minus the deferred rebinding residual).

…min exposure warning

Addresses the data-plane hardening items (area 3, issue #9).

- DP-4: replace the per-byte `byte as char` query decoder (which corrupted
  multi-byte UTF-8, e.g. %C3%A9) with one canonical UTF-8-correct
  `percent_decode`, and apply it to captured path-parameter values too — so
  routing, validation, and dispatch all agree on the decoded value. Path
  segments are still matched raw, so `%2F` stays a literal slash within its
  segment rather than acting as a separator.
- DP-5: enforce header limits on the raw HeaderMap. `HeaderMap::len()` counts
  every header line, so duplicate names can no longer undercount the header
  limit, and each value is size-checked (not just the last for a given name).
- DP-8: the unauthenticated admin port (/health, /metrics, /provenance) now
  logs a startup warning when bound to a non-loopback address, since
  /provenance and /metrics expose build/operational metadata. Documented.

Also updates the validation integration test to expect 413 (payload-too-large)
for oversized bodies, matching the RFC-correct status introduced in PR #94.

AR rebinding residual (pin the vetted IP via a custom DNS resolver to close the
resolve-then-connect TOCTOU) is deferred: it is a cross-cutting refactor of the
WASM HTTP client's DNS path. Left tracked in #9.
@ndreno ndreno merged commit 7cda19e into main Jul 2, 2026
13 checks passed
@ndreno ndreno deleted the security/data-plane-misc branch July 2, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant